﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using GomeeSoft.src.classes;

namespace GomeeSoft.src.control
{
    public partial class UCDataGrid : UserControl
    {
        // Encapsulation ******************************************************************
        #region Encapsulation
        private DataTable dataSource;
        public DataTable DataSource
        {
            get { return dataSource; }
            set { dataSource = value; sortedColumn = -1; PaintGrid(); }
        }
        public bool Selectable;
        private int sortedColumn = -1;
        private int sortedOrder = -1;
        public LinkedList<UCDataColumn> dataColumns;
        public LinkedList<CheckBox> dataRowSelect;
        #endregion

        // Initialization *****************************************************************
        #region Initialization
        public UCDataGrid()
        {
            InitializeComponent();
            dataColumns = new LinkedList<UCDataColumn>();
            dataRowSelect = new LinkedList<CheckBox>();
        }

        private void UCDataGrid_Load(object sender, EventArgs e)
        {
            PaintGrid();
        }
        #endregion

        // Resize *************************************************************************
        #region Resize
        private void UCDataGrid_Resize(object sender, EventArgs e)
        {
            if (dataColumns.Count > 0)
            {
                int colWidth = 0;
                for (int col = 0; col < dataColumns.Count - 1; col++)
                    colWidth += dataColumns.ElementAt<UCDataColumn>(col).ColumnWidth;
                if (colWidth < Width)
                    if (Selectable)
                        dataColumns.Last<UCDataColumn>().ColumnWidth = Width - colWidth - 18;
                    else
                        dataColumns.Last<UCDataColumn>().ColumnWidth = Width - colWidth;
            }
            Invalidate();
        }
        #endregion

        // Paint **************************************************************************
        #region Paint
        private void UCDataGrid_Paint(object sender, PaintEventArgs e)
        {
            PaintBackground(sender, e);
        }

        private void PaintBackground(object sender, PaintEventArgs e)
        {
            Point p = new Point(0,0);
            Size s = new Size(Width, 18);
            Color c = Color.FromArgb(225, 234, 253);
            SolidBrush b = new SolidBrush(c);
            e.Graphics.FillRectangle(b, new Rectangle(p, s));

            p.Offset(0, 36);
            for (int i = p.Y; p.Y < Height; p.Offset(0, 36))
            {
                c = Color.FromArgb(236, 240, 251);
                b = new SolidBrush(c);
                e.Graphics.FillRectangle(b, new Rectangle(p, s));
            }

            p = new Point(0, 0);
            c = Global.GetColor(Global.UCButtonBorderDark);
            Pen pen = new Pen(c);

            if (Selectable)
                p.Offset(18, 0);

            for (int i = 0; i < dataColumns.Count; i++)
            {
                UCDataColumn col = dataColumns.ElementAt<UCDataColumn>(i);
                s = new Size(col.ColumnWidth, 18);

                if (i > 0)
                {
                    Point p1 = new Point(p.X, 2);
                    Point p2 = new Point(p.X, 15);
                    e.Graphics.DrawLine(pen, p1, p2);
                }

                if (sortedColumn == i)
                {
                    Point[] tri = new Point[3];
                    SolidBrush sb = new SolidBrush(Global.GetColor(Global.UCButtonBorderDark));
                    if (sortedOrder < 0)
                    {
                        tri[0] = new Point(p.X + s.Width - 12, p.Y + 4);
                        tri[1] = new Point(p.X + s.Width - 2, p.Y + 4);
                        tri[2] = new Point(p.X + s.Width - 7, p.Y + 14);
                    }
                    else
                    {
                        tri[0] = new Point(p.X + s.Width - 12, p.Y + 14);
                        tri[1] = new Point(p.X + s.Width - 2, p.Y + 14);
                        tri[2] = new Point(p.X + s.Width - 7, p.Y + 4);
                    }
                    e.Graphics.FillPolygon(sb, tri);
                }
                p.Offset(col.ColumnWidth, 0);
            }
        }

        private void PaintGrid()
        {
            Controls.Clear();
            dataRowSelect.Clear();

            PaintHeader();
            if (dataSource != null)
            {
                for (int i = 0; i < dataSource.Rows.Count; i++)
                {
                    PaintDetail(i);
                }
            }
            Invalidate();
        }

        private void PaintHeader()
        {
            Point p = new Point(0, 0);
            Size s = new Size();

            if (Selectable)
            {
                s = new Size(18, 18);
                CheckBox cb = new CheckBox();
                cb.AutoSize = false;
                cb.Location = p;
                cb.Size = s;
                cb.BackColor = Color.Transparent;
                cb.CheckAlign = ContentAlignment.MiddleCenter;
                cb.Click += new EventHandler(HeaderCheckBoxClick);
                Controls.Add(cb);
                dataRowSelect.AddLast(cb);

                p.Offset(s.Width, 0);
            }

            for (int i=0; i<dataColumns.Count; i++)
            {
                UCDataColumn c = dataColumns.ElementAt<UCDataColumn>(i);
                s = new Size(c.ColumnWidth, 18);

                Label lb = new Label();
                lb.AutoSize = false;
                lb.Location = p;
                lb.Size = s;
                lb.BackColor = Color.Transparent;
                lb.ForeColor = Global.GetColor(Global.UCButtonForeColor);
                lb.TextAlign = ContentAlignment.MiddleLeft;
                lb.Text = c.ColumnCaption;
                lb.DoubleClick += new EventHandler(HeaderOrderColumn);
                Controls.Add(lb);
     
                p.Offset(c.ColumnWidth, 0);
            }
        }

        private void PaintDetail(int row)
        {
            Point p = new Point(0, row * 18 + 18);
            Size s = new Size();
            DataRow dataRow = dataSource.Rows[row];

            if (Selectable)
            {
                s = new Size(18, 18);

                CheckBox cb = new CheckBox();
                cb.AutoSize = false;
                cb.Location = p;
                cb.Size = s;
                cb.BackColor = Color.Transparent;
                cb.CheckAlign = ContentAlignment.MiddleCenter;
                cb.Click += new EventHandler(DetailCheckBoxClick);
                Controls.Add(cb);
                dataRowSelect.AddLast(cb);

                p.Offset(s.Width, 0);
            }

            for (int i = 0; i < dataColumns.Count; i++)
            {
                UCDataColumn c = dataColumns.ElementAt<UCDataColumn>(i);
                s = new Size(c.ColumnWidth, 18);

                Label lb = new Label();
                lb.AutoSize = false;
                lb.Location = p;
                lb.Size = s;
                lb.BackColor = Color.Transparent;
                lb.TextAlign = c.ColumnAlign;
                lb.Text = dataRow[c.ColumnName].ToString();
                Controls.Add(lb);
                
                p.Offset(c.ColumnWidth, 0);
            }
        }
        #endregion

        // Internal Class *****************************************************************
        #region Internal Class
        public class UCDataColumn
        {
            // Encapsulation **************************************************************
            #region Encapsulation
            private string columnName;
            public string ColumnName
            {
                get { return columnName; }
                set { columnName = value; }
            }
            private string columnCaption;
            public string ColumnCaption
            {
                get { return columnCaption; }
                set { columnCaption = value; }
            }
            private Type columnType;
            public Type ColumnType
            {
                get { return columnType; }
                set { columnType = value; }
            }
            private int columnWidth;
            public int ColumnWidth
            {
                get { return columnWidth; }
                set { columnWidth = value; }
            }
            private ContentAlignment columnAlign;
            public ContentAlignment ColumnAlign
            {
                get { return columnAlign; }
                set { columnAlign = value; }
            }
            #endregion

            // Initialization *************************************************************
            #region Initialization
            public UCDataColumn(string AColumnName, string AColumnCaption)
            {
                columnName = AColumnName;
                columnCaption = AColumnCaption;
                columnType = typeof(System.String);
                columnWidth = 100;
                columnAlign = ContentAlignment.MiddleLeft;
            }
            public UCDataColumn(string AColumnName, string AColumnCaption, Type AColumnType)
            {
                columnName = AColumnName;
                columnCaption = AColumnCaption;
                columnType = AColumnType;
                columnWidth = 100;
                columnAlign = ContentAlignment.MiddleLeft;
            }
            public UCDataColumn(string AColumnName, string AColumnCaption, Type AColumnType, int AColumnWidth)
            {
                columnName = AColumnName;
                columnCaption = AColumnCaption;
                columnType = AColumnType;
                columnWidth = AColumnWidth;
                columnAlign = ContentAlignment.MiddleLeft;
            }
            public UCDataColumn(string AColumnName, string AColumnCaption, Type AColumnType, int AColumnWidth, ContentAlignment AColumnAlign)
            {
                columnName = AColumnName;
                columnCaption = AColumnCaption;
                columnType = AColumnType;
                columnWidth = AColumnWidth;
                columnAlign = AColumnAlign;
            }
            #endregion
        }
        #endregion

        // Business Logic *****************************************************************
        #region Business Logic
        public void AddDataColumn(UCDataColumn c)
        {
            dataColumns.AddLast(c);
        }

        private void HeaderOrderColumn(Object sender, EventArgs e)
        {
            Label lb = (Label)sender;
            for (int i = 0; i < dataColumns.Count; i++)
            {
                UCDataColumn c = dataColumns.ElementAt<UCDataColumn>(i);
                if (c.ColumnCaption == lb.Text)
                {
                    // Checking sorting status
                    if (sortedColumn == i && sortedOrder < 0)
                        sortedOrder = 1;
                    else if (sortedColumn == i && sortedOrder > 0)
                        sortedOrder = -1;
                    else
                    {
                        sortedColumn = i;
                        sortedOrder = -1;
                    }

                    // Sorting datarow
                    DataRow[] makes;
                    if (sortedOrder < 0)
                        makes = dataSource.Select("", c.ColumnName);
                    else
                        makes = dataSource.Select("", c.ColumnName + " DESC");
                    DataTable newDataTable = dataSource.Clone();
                    newDataTable.Rows.Clear();
                    for (int row = 0; row < makes.Count<DataRow>(); row++)
                        newDataTable.ImportRow(makes.ElementAt<DataRow>(row));
                    dataSource = newDataTable;
                    PaintGrid();
                    break;
                }
            }
        }


        private void HeaderCheckBoxClick(Object sender, EventArgs e)
        {
            bool selectAll = ((CheckBox)(dataRowSelect.ElementAt<CheckBox>(0))).Checked;
            for (int row = 1; row < dataRowSelect.Count; row++)
                ((CheckBox)(dataRowSelect.ElementAt<CheckBox>(row))).Checked = selectAll;
        }

        private void DetailCheckBoxClick(Object sender, EventArgs e)
        {
            bool selectAll = true;
            for (int row = 1; row < dataRowSelect.Count; row++)
                if (!((CheckBox)(dataRowSelect.ElementAt<CheckBox>(row))).Checked)
                    selectAll = false;
            
            ((CheckBox)(dataRowSelect.ElementAt<CheckBox>(0))).Checked = selectAll;
        }
        #endregion
    }
}
